<?php
declare(strict_types=1);

namespace App\AdminApi\Module\System\Service;

use App\Common\Model\System\ConfigureModel;
use Zms\AdminElementPlus\FormCreate\Form;
use Zms\AdminHelper\Callback;
use Zms\Basics\BasicsServe;
use Zms\Exception\AppException;
use Zms\Unit\Arr;
use Zms\Unit\Str;

class ConfigureService extends BasicsServe
{

    /**
     * @return ConfigureModel::class
     */
    public static function model(): string
    {
        return ConfigureModel::class;
    }

    /**
     * 清空无效配置
     * @return void
     */
    public function clearInvalidConfigure(): void
    {
        $keys = [];
        foreach ($this->getClassify() as $item) {
            $keys[] = $item['key'];
            $children = $item['children'] ?? [];
            foreach ($children as $row) {
                $keys[] = $row['key'];
            }
        }
        if (count($keys) > 0) {
            $this->search()->whereNotIn('classify', $keys)->delete();
        }
    }

    /**
     * 获取配置分类
     * ['key'=>'','label'=>'','children=>[]]
     * @return array
     */
    public function getClassify(): array
    {
        return [
            ['key' => 'system', 'label' => '系统设置', 'show' => true],
            ['key' => 'admin', 'label' => '后台设置', 'show' => true],
            ['key' => 'map', 'label' => '地图配置', 'show' => true],
            ['key' => 'sms', 'label' => '短信配置', 'show' => true],
            ['key' => 'ai', 'label' => 'AI配置', 'show' => true],
            ['key' => 'pwd', 'label' => '密码规则', 'show' => true,
                'children' => [
                    ['key' => 'admimpwd', 'label' => '后台密码规则', 'show' => true],
                ]
            ],
            ['key' => 'uploader', 'label' => '上传配置', 'show' => true],
        ];
    }

    /**
     * 获取配置表单
     * @param string $key
     * @param string $action
     * @return array
     * @throws AppException
     */
    public function getForm(string $key, string $action): array
    {
        $rule = $this->getFormRule($key);
        return Form::create('配置修改', $action)
            ->labelWidth('150px')
            ->setRules($rule)
            ->setOptionFormInline(true)
            ->toArray();
    }

    /**
     * 获取对应分组表单
     * @param string $key
     * @return array
     * @throws AppException
     */
    public function getFormRule(string $key): array
    {
        $formName = Str::doubleToHump('get-' . ucfirst($key) . '-form-rule', '-');
        if (!in_array($formName, get_class_methods($this))) {
            throw new AppException("尚未配置相关表单");
        }
        return array_reverse(call_user_func([$this, $formName], $this->get($key, [])));
    }

    /**
     * 获取配置
     * @param string $key
     * @param mixed $default
     * @return mixed
     */
    public function get(string $key = '', mixed $default = null): mixed
    {
        $kyes = Str::explode('/', $key);
        return Callback::cache("system.conf.$key", function () use ($kyes, $default) {
            $conf = $this->getConfAll();
            if (count($kyes) === 0 || $kyes[0] === '') {
                return $conf;
            }
            $value = Arr::get($conf, $kyes[0], $default);
            return match ($kyes[1] ?? 'default') {
                'int' => (int)$value,
                'float' => (float)$value,
                'string' => (string)$value,
                default => $value,
            };
        });
    }

    /**
     * 获取全部配置
     */
    private function getConfAll(): array
    {
        $all = $this->search()->select(['classify', 'value'])->get()->toArray();
        $confData = [];
        foreach ($all as $item) {
            $confData[$item['classify']] = $item['value'];
        }
        return $confData;
    }

    /**
     * 写入配置
     * @param string $key
     * @param array $data
     * @return bool
     */
    public function writeConfiguration(string $key, array $data): bool
    {
        $checkMethod = 'check' . ucfirst($key) . 'Data';
        if (in_array($checkMethod, get_class_methods($this))) {
            $data = call_user_func([$this, $checkMethod], $data);
        }
        $configuration = $this->search(['classify' => $key])->first();
        if (!$configuration) {
            /**
             * @var ConfigureModel $configuration
             */
            $configuration = $this->getModel();
            $configuration->classify = $key;
        }
        $configuration->value = $data;
        return $configuration->save();
    }
}